package 基础语法;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;

public class Stream流 {
    public static void main(String[] args) {
        ArrayList<String> arrayList = new ArrayList<>();
        Collections.addAll(arrayList, "k1", "k2", "k3", "k4", "k5", "k5");// 注意这个工具类
        // Collections.shuffle(arrayList);// 随机打乱，只是演示

        Stream<String> stream = arrayList.stream();// stream是collection接口中的方法，其子类可以直接调用

        stream = stream.filter(item -> {// 是一个@FunctionalInterface得类，其中需要重写的方法是 boolean test(T t);
            if (item.equals("k1"))// 去掉k1
                return false;
            return true;

        });// 会返回一个新得流，必须接收，不然后面再用这个变量就会报错
        stream.forEach(item -> System.out.println(item));// 函数参数是一个那个啥接口，可以用lambda表达式
        System.out.println();
        stream = arrayList.stream();
        stream.limit(2).// 获取前两个元素
                forEach(item -> System.out.println(item));// 属于“终结”方法，后面不能再链式调用

        System.out.println();
        stream = arrayList.stream();
        stream.skip(2).// 跳过前两个元素
                forEach(item -> System.out.println(item));

        System.out.println();
        stream = arrayList.stream();
        stream.distinct().// 去重，依赖hashCode和equals方法
                forEach(item -> System.out.println(item));
        System.out.println();
        Stream<String> stream1 = arrayList.stream();
        Stream<String> stream2 = arrayList.stream();
        Stream.concat(stream2, stream1).forEach(item -> System.out.println(item));// 将两个流合并

        System.out.println();
        stream = arrayList.stream();
        stream.map(item -> {// 改变数据类型. 参数所属的接口由@FunctionalInterface修饰，需要重写的是 R apply(T t);R是要转换的类型，T是 原本得类型
            int last = Integer.parseInt(item.charAt(1) + "");
            return last;

        }).forEach(item -> {
            System.out.println(item);
        });

        stream = arrayList.stream();
        Object[] r = stream.toArray();// 属于终结方法，不能再链式编程
        stream = arrayList.stream();
        String[] r1 = stream.toArray(item -> {// 负责创建一个指定类型的数组
            // 这个参数的接口由@FunctionalInterface修饰，需要重写：R apply(int value);
            return new String[item];// value是需要的数组的 长度，R是类型

        });// 属于终结方法，不再链式编程
        System.out.println(r1.length + "_" + r1[0]);

        stream = arrayList.stream();
        List<String> rl = stream.collect(Collectors.toList());// 属于终结方法，不能再链式编程
        System.out.println(rl);
        stream = arrayList.stream();
        Set<String> sl = stream.collect(Collectors.toSet());// 属于终结方法，不能再链式编程
        System.out.println(sl);
        stream = arrayList.stream();
        Map<String, String> ml = stream.distinct()// 去重一下免得 有重复的键，会报错
                .collect(Collectors.toMap(item -> {// Function<? super T, ? extends K>,需要重写的是 R apply(T
                                                   // t);T是流中每个数据的类型，R是返回值的类型
                    return item;// 限定了键得值和类型String。就把这个作为键
                }, item -> {
                    return item.charAt(1) + "";// 限定了值的值和类型String
                }));
        System.out.println(ml);
        testMap();
        testArray();
        TestOther();
        example1();

    }

    static void example1() {//// 去重重复元素，每个元素加个字符o,去掉k1,获取前3个元素，收集为List并输出，全程需要使用链式编程
        ArrayList<String> arrayList = new ArrayList<>();
        Collections.addAll(arrayList, "k1", "k2", "k3", "k4", "k5", "k5");// 注意这个工具类
        arrayList.stream()
                .distinct().map(item->{
                    return item+"o";//源和目标类型都是String
                })
                .filter(item -> {
                    if (item.equals("k1"))
                        return false;
                    return true;
                })
                .limit(3).collect(Collectors.toList()).stream().forEach(item -> {
                    System.out.println(item+"——UUI");
                });
        ;
    }

    // 双列集合（Map）
    static void testMap() {
        HashMap<String, String> hashMap = new HashMap<>();
        hashMap.put("k1", "v1");
        hashMap.put("k2", "v2");
        hashMap.put("k3", "v3");

        Set<Map.Entry<String, String>> set = hashMap.entrySet();

        Stream stream = set.stream();
        stream.forEach(item -> System.out.println(item));

    }

    static void testArray() {
        String[] strings = new String[] { "aa", "bb" };
        Stream<String> stream = Arrays.stream(strings);
        stream.forEach(item -> System.out.println(item));

        int[] i = new int[] { 1, 2, 3 };

        IntStream stream2 = Arrays.stream(i);

        stream2.forEach(item -> System.out.println(item));

        Stream.of(strings).forEach(item -> System.out.println(item));// 对于引用类型，传递数组是可以和可变参数对应得
        Stream.of(i).forEach(item -> System.out.println(item + "___"));// 对于基本类型，会把数组整体作为一个元素

    }

    static void TestOther() {
        Stream<String> stream = Stream.of("hh", "kk", "aa");
        stream.forEach(item -> System.out.println(item));
        Stream stream1 = Stream.of("klkl", 1);
        stream1.forEach(item -> System.out.println(item));

    }

}
